CanIf模块在AUTOSAR架构中位于底层CAN驱动(CanDrv)与上层通信服务模块(如PduR、、、CanNm、、、CanTp等)之间实际上就是在Can驱动的基础上再次封装了一层,,,,供上层统一使用,,,如下图所示:
其主要功能包括:
实现Pdu数据的收发,,,为上层模块与底层驱动间通信提供对应的收发接口;
实现CAN控制器模式的控制,,通过上层模块下发模式切换请求对应修改控制器模式;
实现Pdu模式控制,,,通过上层模块下发通道模式切换请求对应修改Pdu模式。。。。
关于Pdu详细概念,,,,建议跳转查看:
在介绍CanIf相关功能前,,,,尊龙时凯首先来理解几个概念:Hardware Object Handles(HOH)、、、Hardware Transmit Handles(HTH)和Hardware Receive Handles(HRH)。。。
HOH:是CAN中邮箱的数据结构抽象,,它包括CanId、、、DataLength(数据长度)和数据等CAN帧相关信息。。。。
HRH:是HOH中的一种,,,,用于引用一个CAN控制器邮箱的接收Handle(句柄)。。。一个HRH可以通过配置为FullCan类型用于接收一个特定的CanId或者配置为BasicCan类型用于接收范围内的一组CanId。。。。
HTH:是HOH中的一种,,,用于引用一个CAN控制器邮箱的发送Handle(句柄)。。
Full CAN:一个HOH只能接收或者发送一个CAN报文(或者说一个L-PDU),,,HOH可以配置成HTH或者HRH。。。
Basic CAN:一个HOH接收或者发送多个CAN 报文(或者说多个L-PDU),,,,HOH可以配置成HTH或者HRH。。
HOH实质就是存放收/发CAN报文信息的RAM区,,该区域可以按需所取,,,,也就是说:根据项目的情况(收/发的CAN报文数目),,配置Message RAM使用的空间,,,,实际工程,,,建议全部使用。。Message RAM就好比一块蛋糕,,,,总大小是一定的,,你能吃多少,,,,就切多少。。。。
下图体现了CanIf与硬件对象句柄的映射路径:
如果在CAN总线中接收到符合配置的CAN帧,,,CanDrv通过调用CanIf的CanIf_RxIndication ()接口,,将接收到CAN报文数据组装成Pdu数据向上层模块传递并在上层模块中进行评估和处理,,,,上层模块不能直接操作或访问CanDrv的缓冲区。。
HRH标识CAN硬件接收句柄,,,,接收CAN帧。。。。在CanDrv中调用CanIf_RxIndication(),,,,指示接收到CAN帧后,,,CanIf将依据接收CAN帧的HRH配置(FullCan或BasicCan)匹配到对应的Pdu,,根据配置进行不同处理。。。。
FullCan:HRH接收到的为特定的CAN帧,,CanDrv中调用CanIf_RxIndication()时得到标准的Pdu,,该Pdu将在CanIf中依据配置的CanId进行判断是否为FullCan。。。。为FullCan则进行数据长度检查,,,检查当前接收Pdu是否是一个完整的CAN数据帧。。。。校验通过后CanIf通过CanIfRxPduUserRxIndicationUL,CanIfRxPduUserRxIndicationName两个配置参数识别是否配置了目标上层模块,,若配置上层模块将该Pdu数据传递至指定模块中。。。在传递过程中CAN硬件接收句柄序号会被锁定,,直到复制到上层模块缓冲区中结束后立即释放。。。
BasicCan:HRH依据配置的CanId范围(硬件过滤)接收到的CAN帧,,,CanDrv中调用CanIf_RxIndication()时得到标准的Pdu,,,该Pdu将在CanIf中依据配置的CanId范围进行判断是否为需要接收的Pdu(软件过滤)。。。。若为需要接收Pdu则进行数据长度检查,,检查当前接收Pdu是否是一个完整的CAN数据帧。。。校验通过后CanIf通过CanIfRxPduUserRxIndicationUL、、、、CanIfRxPduUserRxIndicationName两个配置参数识别是否配置了目标上层模块,,,,若配置上层模块将该Pdu数据传递至指定模块中。。。。在传递过程中CAN硬件接收句柄序号会被锁定,,,,直到复制到上层模块缓冲区中结束后立即释放。。。。
CanIf的数据接收流程如下所示:
再来看一下Pdu接收的函数接口调用流程,,,这里还是以中断模式为例:
当CanController接收到数据触发接收中断后,,,先判断是否需用临时缓冲区进行数据规范化并做相应处理,,,接着CanIf模块通过CanIf_RxIndication函数接收数据,,,进行软件过滤、、L - PDU分配等操作,,,再经User_RxIndication函数指示给用户层,,,期间依情况进行数据复制,,最后CanController验证硬件对象并准备接收下次中断。。
CanIf的发送请求函数CanIf_Transmit()是上层模块请求发送Pdu的通用接口。。如果CanDrv能够将PDU数据写入CAN硬件传输对象中,,则发起的传输请求成功完成。。上层模块通过调用CanIf_Transmit ()来发起一个发送请求。。
CanIf_Transmit()对PDU发送前执行以下操作:
检查CanIf的发送状态(控制器模式、、Pdu通信模式)
当使用多个CanDrv时,,,,匹配对应的CanDrv
根据配置找到对应的CAN硬件传输对象HTH
调用CanDrv的Can_Write()
在CanIf收到上层模块的发送请求后,,,函数CanIf_Transmit()通过PduId找到对应的HTH邮箱,,并调用函数Can_Write()。。
若发送成功,,CanDrv将调用CanIf_TxConfirmation()通知CanIf模块,,当前发送数据成功发送可以发送下一个Pdu数据。。。。CanIf将接收到的通知通过配置中的<User TxConfirmation>(User:上层模块)参数,,,通知到上层模块可继续请求发送下一个Pdu数据。。。。
若发送失败,,,且Pdu未配置发送缓冲,,,,则CanIf_Transmit()将返回E_NOT_OK;若启用了发送缓冲,,,将本次发送的Pdu数据存储在缓冲区CanIfTxBuffer中,,,CanIf_Transmit()也会返回E_OK值,,,,CanIf通过CanIf_TxConfirmation()回调处理未完成的发送,,使上层无需重新提出传输请求,,在CanIf_TxConfirmation()中再次处理发送后,,,,若仍未成功,,,,将依据CanIf中相关处理方式(如丢弃或插入缓冲中待HTH空闲时重新发送等)进行不同操作。。。
CanIf的数据发送流程如下所示:
传输过程的函数调用关系如下图:
发送完成后,,底层驱动会调用上层通知函数通知上层发送完成,,,以便上层进一步处理,,,,整个流程如下图所示:
在CanIf中无论是接收还是发送,,,都需要对控制器模式进行控制,控制器共有如下四种状态:
CANIF_CS_UNINIT:控制器未初始化,,,,需将控制初始化后进行后续操作
CANIF_CS_STOPPED :控制器处于停止状态,,,,接收和发送操作无法进行
CANIF_CS_STARTED:控制器处于启动状态,,,,可以进行接收和发送操作
CANIF_CS_SLEEP: 控制器处于睡眠状态,,在唤醒前无法接收和发送操作,,唤醒后可以继续进行接收和发送操作
在初始完成后,,,,控制器模式处于STOPPED状态,,无法进行接收和发送操作。。但上层模块可通过调CanIf_SetControllerMode()接口请求更改CAN控制器状态。。。。上层模的请求通过CanIf经过CanDrv的特定API传递到指定的CAN控制器。。。。CanIf通过调用函数CanIf_SetControllerMode()或CanIf_ControllerBusOff()接受每个状态转换请求。。。CanIf不决定CAN控制器请求的模式转换是否有效。。。。CanIf仅通过获取当前模式和执行请求的模式转换来与CanDrv交互确定当前控制器状态,,仅提供一个桥梁的工作。。。。
CanIf设置控制模式如下图所示:
在CanIf中Pdu的接收和发送除受控制器模式影响外,,,还受Pdu通信模式控制,,,只有当控制模式处于CANIF_CS_STARTED时才允许更改Pdu通道模式,,,不同模式下Pdu的通信能力如下:
CANIF_OFFLINE:关闭Pdu通道,,不允许进行Pdu的接收与发送操作
CANIF_ONLINE:开启Pdu通道,,,允许进行Pdu的接收与发送操作
CANIF_TX_OFFLINE:开启发送Pdu通道关闭Pdu接收通道,,允许进行Pdu的发送但不允许接收Pdu
CANIF_TX_OFFLINE_ACTIVE:模拟成功传输
在初始化期间,,,CanIf应该将每个通道切换到CANIF_OFFLINE。。CanIf通过调用CanIf_GetPduMode()提供关于当前Pdu通道模式的信息
对于切换到CANIF_OFFLINE模式的物理通道,,,CanIf应该:
防止将相关L-PDU的传输请求CanIf_Transmit()转发给CanDrv。。。
清除相应的CanIf传输缓冲区。。。。
防止调用上层模块的接收通知回调服务。。
防止调用上层模块的传输确认回调服务。。
如果底层调用CanIf_SetControllerMode()或CanIf_ControllerBusOff(),,则CanIf应将相应通道的PDU通道模式设置为CANIF_TX_OFFLINE。。。
对于切换到CANIF_ONLINE模式的物理信道,,,,CanIf应该:
允许将相关L-PDU的传输请求CanIf_Transmit()转发到CanDrv。。。
支持调用上层模块的接收指示回调服务。。。
允许调用上层模块的传输确认回调服务。。。
如果CanIfTxOfflineActiveSupport为TRUE,,,CanIf提供通过CANIF_TX_OFFLINE_ACTIVE模式来模拟成功传输。。。对于每个被分配到CANIF_TX_OFFLINE_ACTIVE模式信道的pdu CanIf会立即调用上层模块的传输确认回调服务,,,,而不是在调用CanIf_Transmit()时将Pdu缓冲或转发到CanDrv。。
Pdu通道模式转化如下图所示:
本章节的配置项截图均来自EasySAR网页端的配置工具
该容器主要配置CanIf控制的控制器相关信息。。。。
该容器主要配置分配任务相关信息。。。。
该容器主要配置CanIf初始化时相关参数
该同期主要配置CanIf缓冲区相关参数
该容器主要配置CanIfHoh中Hrh相关参数
该容器主要配置Hrh中接收范围相关参数
该容器主要配置CanIfHoh中Hth相关参数
该容器主要配置接收Pdu的相关参数
该容器主要配置发送Pdu的相关参数
该容器主要配置私有接口相关参数
该容器主要配置公共接口相关参数